/*
    Modified from The Loki Library
    Modified by : 2013 darkcat

    Copyright (c) 2001 by Andrei Alexandrescu

    This code accompanies the book:
    Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design 
        Patterns Applied". Copyright (c) 2001. Addison-Wesley.
    Permission to use, copy, modify, distribute and sell this software for any 
        purpose is hereby granted without fee, provided that the above copyright 
        notice appear in all copies and that both that copyright notice and this 
        permission notice appear in supporting documentation.
    The author or Addison-Wesley Longman make no representations about the 
        suitability of this software for any purpose. It is provided "as is" 
        without express or implied warranty.
*/

#pragma once

// nx...
#include "config/general.h"
// nx_types
#include "type/typelist.h"
// nx::pointer
#include "memory/pointer.h"

//////////////////////////////////////////////////////////////////////////
NX_BEG
//////////////////////////////////////////////////////////////////////////

namespace private_
{
    struct FunctorBase_
    {
        virtual ~FunctorBase_() {}
    };

    template <typename R, class List_>
    struct FunctorImpl_;
    
    template <typename R>
    struct FunctorImpl_<R, type::null_t> : 
           FunctorBase_
    {
        virtual FunctorImpl_* clone() const = 0;
        virtual R operator()(void) = 0;
    };

    template <typename R, typename T1>
    struct FunctorImpl_<R, NX_TYPES(T1) > : 
           FunctorBase_
    {
        virtual FunctorImpl_* clone() const = 0;
        virtual R operator()(T1) = 0;
    };

    template <typename R, typename T1, typename T2>
    struct FunctorImpl_<R, NX_TYPES(T1, T2) > : 
           FunctorBase_
    {
        virtual FunctorImpl_* clone() const = 0;
        virtual R operator()(T1, T2) = 0;
    };
}

template <typename R, class List_>
struct Functor
{
protected:
    typedef private_::FunctorImpl_<R, List_> impl_t;
    nx::pointer<impl_t> impl_;

public:
    Functor(void);
    Functor(const Functor& f);
    explicit Functor(const nx::pointer<impl_t>& f);

    Functor& operator=(const Functor& f);
};

//////////////////////////////////////////////////////////////////////////
NX_END
//////////////////////////////////////////////////////////////////////////
